var express = require("express");
var router = express.Router();

const { Chapter, Course } = require("../../models");
// 复杂查询
const { Op, where } = require("sequelize");
// 自定义异常
const { NotFound, BadRequest } = require("http-errors");
// 自定义响应
const { success, failure } = require("../../utils/responses");
const { delKey } = require("../../utils/redis");

/**
 * 获取章节列表
 * GET /admin/chapters
 * @query { limit, offset }
 * @return 章节列表
 */
router.get("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    // 章节的分页查询
    const query = req.query;
    // 当前页码 默认 1
    const currentPage = Math.abs(+query.currentPage) || 1;
    // 每页多少条数据 默认 10
    const pageSize = Math.abs(+query.pageSize) || 10;
    // 偏移量
    const offset = (currentPage - 1) * pageSize;
    // 必须传课程ID
    if (!query.courseId) {
      throw new BadRequest("获取章节列表失败，课程ID不能为空。");
    }
    // 查询课程ID是否存在
    const course = await Course.findOne({
      where: {
        id: query.courseId,
      },
    });
    if (!course) {
      throw new Error("获取章节列表失败，课程不存在。");
    }

    const condition = {
      ...getCondition(),
      where: {},
      order: [
        ["rank", "ASC"],
        ["id", "DESC"],
      ],
      limit: pageSize,
      offset,
    };
    condition.where.courseId = query.courseId;

    if (query.title) {
      condition.where.title = {
        [Op.like]: `%${query.title}%`,
      };
    }
    // 查询所有章节
    const { rows, count } = await Chapter.findAndCountAll(condition);
    // 成功状态码 默认200 正确响应了
    success(res, "查询章节列表成功", {
      chapters: rows,
      pagination: {
        currentPage,
        pageSize,
        total: count,
      },
    });
  } catch (error) {
    failure(res, error);
  }
});
/**
 * 获取章节详情
 * GET /admin/chapters/:id
 * @params id 章节id
 * @return 章节详情
 */
router.get("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const chapter = await getChapter(req);
    // 成功状态码 默认200
    success(res, "查询章节详情成功", { chapter });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 新增章节
 * POST /admin/chapters
 * @body title 标题
 * @body content 内容
 * @return
 */
router.post("/", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const body = filterBody(req);
    // 创建章节，并增加课程章节数
    const chapter = await Chapter.create(body);
    await Course.increment("chaptersCount", {
      where: { id: chapter.courseId },
    });
    await clearCache(chapter);

    // 成功状态码 201 正确响应了，并创建了新的资源
    success(res, "新增章节成功", chapter, 201);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 删除章节
 * DELETE /admin/chapters/:id
 * @params id 章节id
 * @return
 */
router.delete("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const chapter = await getChapter(req);

    // 删除章节，并减少课程章节数
    await chapter.destroy();
    await Course.decrement("chaptersCount", {
      where: { id: chapter.courseId },
    });
    await clearCache(chapter);

    success(res, "删除章节成功");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新章节
 * PUT /admin/chapters/:id
 * @params id 章节id
 * @body title 标题
 * @body content 内容
 * @return 章节详情
 */
router.put("/:id", async function (req, res, next) {
  // 处理异常 try catch
  try {
    const chapter = await getChapter(req);
    // 白名单过滤
    const body = filterBody(req);

    await chapter.update(body);
    await clearCache(chapter);

    success(res, "更新章节成功", { chapter });
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 公共方法: 查询当前章节
 */
async function getChapter(req) {
  // 获取章节ID
  const { id } = req.params;
  const condition = getCondition();
  // 查询章节
  const chapter = await Chapter.findByPk(id, condition);
  // 章节不存在 抛出异常
  if (!chapter) {
    throw new NotFound(`ID: ${id}的章节不存在`);
  }
  // 章节存在
  return chapter;
}

/**
 * 公共方法：关联课程数据
 * @returns {{include: [{as: string, model, attributes: string[]}], attributes: {exclude: string[]}}}
 */
function getCondition() {
  return {
    attributes: { exclude: ["CourseId"] },
    include: [
      {
        model: Course,
        as: "course",
        attributes: ["id", "name"],
      },
    ],
  };
}

/**
 * 公共方法：白名单过滤
 * @param req
 * @returns {{rank: (number|*), video: (string|boolean|MediaTrackConstraints|VideoConfiguration|*), title, courseId: (number|*), content}}
 */
function filterBody(req) {
  return {
    courseId: req.body.courseId,
    title: req.body.title,
    content: req.body.content,
    video: req.body.video,
    rank: req.body.rank,
    free: req.body.free,
  };
}

/**
 * 清除缓存
 * @param chapter
 * @returns {Promise<void>}
 */
async function clearCache(chapter) {
  await delKey(`chapters:${chapter.courseId}`);
  await delKey(`chapter:${chapter.id}`);
}

module.exports = router;
